<?php


namespace App\Event;


use App\HttpController\ExceptionHandler;
use EasySwoole\Component\Di;
use EasySwoole\Component\Singleton;
use EasySwoole\EasySwoole\Config;
use EasySwoole\EasySwoole\Logger;
use EasySwoole\EasySwoole\SysConst;
use EasySwoole\Http\Message\Status;
use EasySwoole\Http\Request;
use EasySwoole\Http\Response;
use EasySwoole\Log\LoggerInterface;
use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\ORM\Db\Connection;
use EasySwoole\ORM\Db\Result;
use EasySwoole\ORM\DbManager;

class Initialize
{
    use Singleton;

    public function initialize(): void
    {
        /** ***************** 注册HTTP控制器错误异常处理 ****************** */
        Di::getInstance()->set(SysConst::HTTP_EXCEPTION_HANDLER, [ExceptionHandler::class, 'handle']);

        /** ***************** 加载配置文件 ********************** */
        Config::getInstance()->loadDir(EASYSWOOLE_ROOT . '/Config');

        $this->orm();

        $this->onRequest();
    }

    private function onRequest()
    {
        Di::getInstance()->set(SysConst::HTTP_GLOBAL_ON_REQUEST, function (Request $request, Response $response) {
            $header = Config::getInstance()->getConf('app.RESPONSE_HEADER');
            foreach ($header as $k => $v) {
                $response->withHeader($k, $v);
            }

            if ($request->getMethod() === 'OPTIONS') {
                $response->withStatus(Status::CODE_OK);
                return false;
            }
            return true;
        });
    }

    /**
     * MYSQL ORM 的配置信息注册
     */
    private function orm(): void
    {
        $config = new \EasySwoole\ORM\Db\Config(Config::getInstance()->getConf('mysql'));
        //连接池配置
        $config->setGetObjectTimeout(3.0); //设置获取连接池对象超时时间
        $config->setIntervalCheckTime(30 * 1000); //设置检测连接存活执行回收和创建的周期
        $config->setMaxIdleTime(15); //连接池对象最大闲置时间(秒)
        $config->setMinObjectNum(5); //设置最小连接池存在连接对象数量
        $config->setMaxObjectNum(20); //设置最大连接池存在连接对象数量
        $config->setAutoPing(5); //设置自动ping客户端链接的间隔

        DbManager::getInstance()->addConnection(new Connection($config));
        DbManager::getInstance()->onQuery(function (Result $res, QueryBuilder $builder, float $start) {
            $queryTime = 0.5;
            $time = bcsub(microtime(true), $start, 3);

            $code = $res->getLastErrorNo();
            $sql = $builder->getLastQuery();

            if ($code != 0) {
                Logger::getInstance()->log("sql code: {$code}  sql: {$sql}  time: {$time}", LoggerInterface::LOG_LEVEL_ERROR, "ERROR");
            }

            if ($time > $queryTime) {
                Logger::getInstance()->log("sql: {$sql}  time: {$time}", LoggerInterface::LOG_LEVEL_WARNING, "WARNING");
            }
        });
    }
}